package com.xmim.server.examples;

import com.xmim.core.container.Container;
import com.xmim.core.container.ServerContainer;
import com.xmim.fulcrum.FulcrumCounter;
import com.xmim.fulcrum.FulcrumFactory;
import com.xmim.fulcrum.FulcrumPathCache;
import com.xmim.fulcrum.discover.AbstractFulcrumDiscover;
import com.xmim.fulcrum.node.DefaultFulcrumServiceNode;
import com.xmim.fulcrum.node.DefaultFulcrumUserNode;
import com.xmim.fulcrum.node.FulcrumServiceNode;
import com.xmim.fulcrum.node.FulcrumUserNode;
import lombok.extern.slf4j.Slf4j;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.CreateMode;

/**
 * IM 节点的ZK协调客户端
 * create by CAOYOU
 **/

@Slf4j
public class ZKFulcrumDiscover extends AbstractFulcrumDiscover {


    //Zk curator 客户端
    private CuratorFramework client;

    public ZKFulcrumDiscover(FulcrumFactory factory, ServerContainer parent) {
        super(factory, parent);
    }


    @Override
    protected void onInit() {
        try {
            // 重试策略:第一次重试等待1s，第二次重试等待2s，第三次重试等待4s
            // 第一个参数：等待时间的基础单位，单位为毫秒
            // 第二个参数：最大重试次数
            ExponentialBackoffRetry retryPolicy = new ExponentialBackoffRetry(1000, 3);
            // 获取 CuratorFramework 实例的最简单的方式
            // 第一个参数：zk的连接地址
            // 第二个参数：重试策略
            client = CuratorFrameworkFactory.newClient(getFactory().getConfig().getZkAddress(), retryPolicy);
            //启动客户端实例,连接服务器
            client.start();
            client.create()
                    .creatingParentsIfNeeded()
                    .withProtection()
                    .withMode(CreateMode.PERSISTENT)
                    .forPath(getFactory().getConfig().getRootPath());
            log.debug("启动zookeeper成功");
        } catch (Exception e) {
            log.debug("启动zookeeper失败：", e);
        }

    }


    @Override
    protected FulcrumCounter createOnlineServixeCounter() {
        return new ZKFulcrumCounter(this, getFactory().getConfig().getCounterServicePath());
    }

    @Override
    protected FulcrumCounter createOnlineUserCounter() {
        return new ZKFulcrumCounter(this, getFactory().getConfig().getCounterUserPath());
    }

    @Override
    protected FulcrumPathCache<FulcrumServiceNode> createServixeCache() {
        ZkFulcrumServicePathCache pathCache = new ZkFulcrumServicePathCache(this);
        pathCache.init(DefaultFulcrumServiceNode.class);
        pathCache.addNode(this.getLocalNode());
        return pathCache;
    }

    @Override
    protected FulcrumPathCache<FulcrumUserNode> createUserCache() {
        ZkFulcrumUserPathCache pathCache = new ZkFulcrumUserPathCache(this);
        pathCache.init(DefaultFulcrumUserNode.class);
        return pathCache;
    }

    @Override
    protected FulcrumServiceNode createLocalNode() throws Exception {
        DefaultFulcrumServiceNode serviceNode = new DefaultFulcrumServiceNode();
        serviceNode.setHost(getFactory().getConfig().getHost());
        serviceNode.setPort(getFactory().getConfig().getPort());
        return serviceNode;
    }

    public CuratorFramework getClient() {
        return client;
    }

    @Override
    protected void onClose() {
        client.close();
    }


}
